<template>
    <el-container style="padding: 20px; max-width: 800px; margin: auto;">
        <transition-group name="list" tag="div" class="container">
            <div v-for="(item, index) in boxes" :key="item.id" class="box"
                :class="{ 'drag-over': dragOverIndex === index }" draggable="true"
                @dragstart="onDragStart($event, index)" @dragover.prevent="onDragOver($event, index)"
                @dragleave="onDragLeave(index)" @drop="onDrop($event, index)">
                <div class="box-header">
                    <el-button icon="el-icon-rank" circle size="mini" class="drag-handle" title="拖拽"
                        @mousedown.stop>拖拽</el-button>
                    <el-button icon="el-icon-delete" circle size="mini" class="delete-btn" title="删除"
                        @click.stop="deleteBox(index)">删除</el-button>
                </div>
                <div class="box-content">
                    {{ item.content }}
                </div>
            </div>
        </transition-group>
    </el-container>
</template>

<script lang="ts" setup>
import { ref } from 'vue'

interface Box {
    id: number
    content: string
}
const boxes = ref<Box[]>([
    { id: 1, content: '盒子 1' },
    { id: 2, content: '盒子 2' },
    { id: 3, content: '盒子 3' },
    { id: 4, content: '盒子 4' }
])
let dragIndex = -1
const dragOverIndex = ref(-1)
const onDragStart = (event: DragEvent, index: number) => {
    dragIndex = index
    event.dataTransfer?.setData('text/plain', String(index))
    event.dataTransfer!.effectAllowed = 'move'
}
const onDragOver = (event: DragEvent, index: number) => {
    if (index !== dragIndex) {
        dragOverIndex.value = index
    }
}
const onDragLeave = (index: number) => {
    if (dragOverIndex.value === index) {
        dragOverIndex.value = -1
    }
}
const onDrop = (event: DragEvent, dropIndex: number) => {
    event.preventDefault()
    if (dragIndex === -1 || dragIndex === dropIndex) {
        dragOverIndex.value = -1
        return
    }
    const draggedItem = boxes.value[dragIndex]
    boxes.value.splice(dragIndex, 1)
    boxes.value.splice(dropIndex, 0, draggedItem)
    dragIndex = -1
    dragOverIndex.value = -1
}
const deleteBox = (index: number) => {
    boxes.value.splice(index, 1)
}
</script>

<style scoped>
.container {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
}

/* 盒子基础样式 */
.box {
    position: relative;
    width: 400px;
    height: 200px;
    border: 1px solid #dcdfe6;
    border-radius: 4px;
    background-color: #f5f7fa;
    box-sizing: border-box;
    padding: 10px;
    user-select: none;
    transition: transform 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}

/* 拖拽时目标盒子高亮和放大 */
.box.drag-over {
    border-color: #409eff;
    box-shadow: 0 0 12px #409effaa;
    transform: scale(1.05);
    z-index: 5;
}

/* 盒子头部按钮 */
.box-header {
    position: absolute;
    top: 8px;
    right: 8px;
    display: flex;
    gap: 8px;
    z-index: 10;
}

.drag-handle {
    cursor: grab;
}

.drag-handle:active {
    cursor: grabbing;
}

.delete-btn {
    cursor: pointer;
}

/* 盒子内容居中 */
.box-content {
    margin-top: 40px;
    font-size: 18px;
    text-align: center;
    line-height: 280px;
    color: #606266;
    user-select: text;
}

/* transition-group 动画 */
.list-move {
    transition: transform 0.3s ease;
}
</style>
